// ITimer.cpp : Implementation of COleTimer

#include "stdafx.h"
#include "IOleTimer.h"


// COleTimer
std::map<DWORD, COleTimer::tagTimerInfo> COleTimer::s_mapInfo;


void COleTimer::OnTimer(int nId, ITimerSink* pSink)
{
	if (!m_bFreeze)
	{
		if (pSink)
		{
			pSink->OnTimer(CComVariant(0));
		}
	}
}

STDMETHODIMP COleTimer::Advise( VARIANT vtimeMin,VARIANT vtimeMax,VARIANT vtimeInterval,DWORD dwFlags,ITimerSink *pTimerSink,DWORD *pdwCookie)
{
	if (!pdwCookie)
	{
		return E_INVALIDARG;
	}

	if (vtimeMin.uintVal == 0 && vtimeInterval.uintVal == 0)
	{
		return E_INVALIDARG;
	}
	if (vtimeInterval.uintVal == 0)
	{
		if (vtimeMin.uintVal <= ::GetTickCount())
		{
			return E_INVALIDARG;
		}

		vtimeInterval.uintVal = vtimeMin.uintVal - ::GetTickCount();
	}

	tagTimerInfo info;
	info.vtimeMin = vtimeMin.uintVal;
	info.vtimeMax = vtimeMax.uintVal;
	info.pTimerSink = pTimerSink;
	info.pTimer = this;
	*pdwCookie = (DWORD)::SetTimer(NULL,0,vtimeInterval.uintVal,TimerObj_TimerProc);

	s_mapInfo[*pdwCookie] = info;

	m_dwCookie = *pdwCookie;
	info.pTimerSink->AddRef();

	return S_OK;
}

STDMETHODIMP COleTimer::Unadvise( DWORD dwCookie) 
{
	::KillTimer(NULL,dwCookie);
		std::map<DWORD, tagTimerInfo>::iterator it = s_mapInfo.find(dwCookie);
		if (it != s_mapInfo.end())
		{
			tagTimerInfo TimeInfo = it->second;
			if (TimeInfo.pTimerSink)
			{
				TimeInfo.pTimerSink->Release();
				TimeInfo.pTimerSink = NULL;;
			}
		}
		s_mapInfo.erase(dwCookie);
		m_dwCookie = 0;

	return S_OK;
}

STDMETHODIMP COleTimer::Freeze( BOOL fFreeze) 
{
	m_bFreeze = fFreeze;
	return S_OK;
}

STDMETHODIMP COleTimer::GetTime(  VARIANT *pvtime)
{
	pvtime->uintVal = ::GetTickCount();
	return S_OK;
}	

VOID CALLBACK COleTimer::TimerObj_TimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
{
	std::map<DWORD, COleTimer::tagTimerInfo>::iterator it = COleTimer::s_mapInfo.find((DWORD)idEvent);
	if (it != COleTimer::s_mapInfo.end())
	{
		it->second.pTimer->OnTimer((DWORD)idEvent,it->second.pTimerSink);
	}
}
